/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * httpd
 * Copyright (C) Dnyanesh Gate 2012 <dnyaneshgate@yahoo.com>
 * 
 * httpd is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * httpd is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <Socket.h>

Socket::Socket(){
	SOCK = -1;
	SOCK = socket(AF_INET,SOCK_STREAM,0);
	if(SOCK < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("SOCKET");
	}
#ifdef DEBUG
	printf("Server Socket created successfully\n");
#endif
}

Socket::~Socket(){
	CloseSocket ();
}

int Socket::Connect(const char* addr, int port){
	int rval = -1;
	int loop = 10;
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(port);
	inet_aton(addr,&(serv_addr.sin_addr));

	while((rval = connect(SOCK,(struct sockaddr*)&serv_addr,sizeof(serv_addr))) < 0 && loop--){
		printf("\rConnecting to Server... %s\t%d",addr,loop);
		sleep(5);
	}
	std::cout<<std::endl;
	if(rval < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("CONNECT");
		CloseSocket();
		return ERROR;
	}
#ifdef DEBUG
	printf("Connected To Server...%s\n",addr);
#endif
	return SUCCESS;
}

int Socket::Send(const char* str, int size){
	if(write(SOCK,str,size) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("WRITE");
		return ERROR;
	}
	return SUCCESS;
}

int Socket::Recv(char *str){
	if(read(SOCK,str,BUFFSIZE) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("READ");
		return ERROR;
	}
	return SUCCESS;
}

int Socket::CloseSocket(){
	if(shutdown(SOCK,SHUT_RDWR) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("SHUTDOWN");
		return ERROR;
	}
	close(SOCK);
	SOCK = ERROR;
#ifdef DEBUG
	printf("Shutting Down Server Connection...\n");
#endif
	return SUCCESS;
}

int Socket::SetSockOpt(int level, int optname, const void *optval,socklen_t optlen){
	if(setsockopt(SOCK,level,optname,optval,optlen) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("SETSOCKOPT");
		return ERROR;
	}
	return SUCCESS;
}

int Socket::GetSockOpt(int level, int optname, void *optval,socklen_t *optlen){
	if(getsockopt(SOCK,level,optname,optval,optlen) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("GETSOCKOPT");
		return ERROR;
	}
	return SUCCESS;
}

ServerSocket::ServerSocket(){
	memset(CLIENT,-1,MAXCLIENTS);
	noOfclients = 0;
}

ServerSocket::~ServerSocket(){
	noOfclients = 0;
}

int ServerSocket::Bind(int port){
	int rval = -1;
	int loop = 10;
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = INADDR_ANY;
	serv_addr.sin_port = htons(port);
#ifdef DEBUG
	printf("Server Socket binding to port:%d\n",port);
#endif
	while((rval = bind(SOCK,(struct sockaddr*)&serv_addr,sizeof(serv_addr))) < 0 && loop--){
		printf("\rwait...  %d",loop);
		fflush(0);
		sleep(5);
	}
	std::cout<<std::endl;
	if(rval < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("BIND");
		CloseSocket();
		return ERROR;
	}

#ifdef DEBUG
	printf("Server Socket binded to port:%d\n",port);
#endif
	return SUCCESS;
}

int ServerSocket::Listen(){
	int rval = listen(SOCK,MAXCLIENTS);
	if(rval < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("LISTEN");
		CloseSocket();
		return ERROR;
	}
#ifdef DEBUG
	printf("listening...\n");
#endif
	return SUCCESS;
}

int ServerSocket::Accept(int i){
	int clilen;
	clilen = sizeof(cli_addr[i]);
	CLIENT[i] = accept(SOCK,(struct sockaddr*)&cli_addr[i],(socklen_t*)&clilen);
	if(CLIENT[i] < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("ACCEPT:");
		CloseSocket();
		return ERROR;
	}
#ifdef DEBUG
	printf("Connection accepted %d\n",i);
#endif
	//noOfClients++;
	return SUCCESS;
}

int ServerSocket::Send(const char* str, int size, int i){
	/*if(write(CLIENT[i],str,size) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("WRITE");
		return ERROR;
	}*/

	if(send(CLIENT[i],str,size,0) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("SEND");
		return ERROR;
	}
	return SUCCESS;
}

int ServerSocket::Recv(char *str,int i){
	if(read(CLIENT[i],str,BUFFSIZE) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("READ");
		return ERROR;
	}
	return SUCCESS;
}

int ServerSocket::CloseConnection(int i){
	if(shutdown(CLIENT[i],SHUT_RDWR) < 0){
		printf("LINE NO: %d\n",__LINE__);
		perror("SHUTDOWN");
		return ERROR;
	}
	close(CLIENT[i]);
	CLIENT[i] = ERROR;
#ifdef DEBUG
	printf("Shutting Down Client Connection... %d\n",i);
#endif
	return SUCCESS;
}
